React - State
Tot nu toe hebben we onze gegevens opgeslagen in een array in een variabele en gaven deze door als props (zie React - Props). Dit is een goed begin, maar wat als we bijvoorbeeld een item uit de array willen verwijderen? Met props hebben we een eenrichtingsgegevensstroom, maar met de state kunnen we privégegevens van een component bijwerken.
Bronnen
- State and Lifecycle, deze pagina legt het concept
state
enlifecycle
in een React component uit.
Een nieuwe react app maken
- Zorg ervoor dat je openstaande Node.js servers afsluit met Ctrl-C.
- Vooraleer de create-react-app op te starten ga je naar de map waarin je het project wil maken. We gaan op Cloud9 een project maken met de naam react-state. En dat project plaatsen we in de root van onze workspace. Zorg er dus voor dat je in de root staat:
jefinghelbrecht:~/workspace $
In plaats van JefInghelbrecht zie je natuurlijk de naam van je eigen workspace. - Om een create-react-app te maken, voer je de volgende instructie in je terminal uit (zorg ervoor dat je de laatste versie van Node hebt geïnstalleerd, zie Een React App maken):
npx create-react-app react-state
Meer info over npx: Introducing npx: an npm package runner - Op Cloud9 moet je telkens opgeven dat je met de nieuwere versie wilt werken:
nvm use 8
- Als de installatie goed verlopen is, ga dan naar de nieuw aangemaakte map en start het project:
cd react-state
npm start - We maken onze eigen standaardtekst en kieperen de voorgeprogrammeerde code overboord. We behouden alleen:
- index.js
- index.css
- We deleten alle overige bestanden in de /src.
- In index.css plakken we de Primitive CSS van Tania Rascia. Je kan dat vervangen door je eigen CSS of door Bootstrap of om het even welk ander CSS framework.
- Verwijder de verwijzingen naar
serviceWorker
in index.js. Delete de gemarkeerde lijnen:import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import * as serviceWorker from './serviceWorker'; ReactDOM.render(<App />, document.getElementById('root')); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: http://bit.ly/CRA-PWA serviceWorker.unregister();
'state' gebruiken om gegevens door te geven
State kan je beschouwen als het opslagen en wijzigen van om het even welk gegeven zonder dat het noodzakelijkerwijs in een database moet worden opgeslagen. Bijvoorbeeld items, die tijdens het shoppen aan een winkelwagentje worden toegevoegd en eventueel weer verwiijderd, vooraleer de aankoop te bevestigen.
- We beginnen met het maken van een
state
-object in het bestand met de naam App.js:import React, { Component } from 'react'; class App extends Component { state = {}; } export default App;
- Het
state
-object bevat al de eigenschappen voor alle gegevens die we in de state willen opslagen. In ons voorbeeld is datalbums
:import React, { Component } from 'react'; class App extends Component { state = { albums: [] }; } export default App;
- We plaatsen de array met de albums van Jommeke in
state.albums
:import React, { Component } from 'react'; class App extends Component { state = { albums: [{ 'nummer': '6', 'titel': 'Het hemelhuis', 'kaft': 'Softcover', 'prijs': '€ 5.22' }, { 'nummer': '7', 'titel': 'De zwarte Bomma', 'kaft': 'Softcover', 'prijs': '€ 5.22' }, { 'nummer': '8', 'titel': 'De ooievaar van Begonia', 'kaft': 'Softcover', 'prijs': '€ 5.22' }, { 'nummer': '9', 'titel': 'De Schildpaddenschat', 'kaft': 'Softcover', 'prijs': '€ 5.22' }, { 'nummer': '10', 'titel': 'De straalvogel', 'kaft': 'Hardcover', 'prijs': '€ 8.22' }, { 'nummer': '11', 'titel': 'De Zonnemummie', 'kaft': 'Softcover', 'prijs': '€ 5.22' } ] }; } export default App;
- De gegevens zitten nu in de
state
. Om een album te kunnen verwijderen uit de tabel, gaan we eenremoveAlbum
methode toevoegen aan deApp
klasse. Om destate
op te vragen halen wethis.state.albums
op met de ES6 methode, die we in React - Props gebruikt hebben. Om destate
te updaten gebruiken we dethis.setState()
methode. Deze methode is een ingebouwde methode van React om destate
te kunnen bewerken. Je moetthis.setState()
gebruiken om een array te wijzigen. Een nieuwe waarde toekennen aanthis.state.property
zal niet weken! We zullen de array filteren gebaseerd op deindex
die we doorgeven. Tenslotte retourneren we de nieuwe gefilterde array. Voeg in App.js de volgende ES6 methode toe:import React, { Component } from 'react'; import Table from './Table'; class App extends Component { removeAlbum = index => { const { albums } = this.state; this.setState({ characters: albums.filter((character, i) => { return i !== index; }) }); } ...
filter
muteert niet maar maakt een nieuwe array aan en is dus voorkeursmethode voor het wijzigen van arrays in JavaScript. Deze specifieke methode gaat na of een opgegevenindex
overeenkomt met één van de indices in de array en het retourneert alle elementen van de array behalve die rij die dezelfdeindex
heeft als de opgegeven index. - We gaan deze functie doorgeven aan de component en een HTML knop weergeven naast elk album die deze functie kan activeren. We geven de
removeAlbum
functie door als een prop aan deTable
component:return ( <div className="container"> <Table albumData={albums} removeAlbum={this.removeAlbum} /> </div> );
- In de return hierboven gebruiken we de albums constante. In React - Props was die in de
render()
methode gedefinieerd. Nu wordt die in destate
van de klasse gedefinieerd. Om die toegankelijk te maken in derender()
methode moeten we naar de state verwijzen:return ( <div className="container"> <Table albumData={this.state.albums} removeAlbum={this.removeAlbum} /> </div> )
- We kopiëren de code van de
Table
component die we gemaakt hebben in React - Props en plaatsen het in een bestand met de naam Table.js in de /src map:import React, { Component } from 'react'; const TableBody = props => { const rows = props.albumData.map((row, index) => { return ( <tr key={index}> <td>{row.nummer}</td> <td>{row.titel}</td> <td>{row.kaft}</td> <td>{row.prijs}</td> </tr> ); }); return <tbody>{rows}</tbody>; } class Table extends Component { render() { const {albumData} = this.props; return ( <table> <TableBody albumData={albumData} /> </table> ); } } export default Table;
- Nu gaan we de
removeAlbum
methode doorgeven aan hetTableBody
element van deTable
component. We geven de methode door als een prop op dezelfde manier als dat we de albumgegevens hebben doorgegeven:class Table extends Component { render() { const {albumData, removeAlbum} = this.props; return ( <table> <TableBody albumData={albumData} removeAlbum = {removeAlbum} /> </table> ); } }
- Nu kunnen we eindelijk die
index
gaan gebruiken die we in de methoderemoveAlbum
gedefinieerd hebben. We geven dekey
/index
aan deTableBody
component door als een parameter zodat defilter
functie weet welk item er uit de lijst verwijderd moet worden. We maken de HTML knop met eenonClick
event en geven deindex
door. In Table.js voegen we de volgende code toe:const TableBody = props => { const rows = props.albumData.map((row, index) => { return ( <tr key={index}> <td>{row.nummer}</td> <td>{row.titel}</td> <td>{row.kaft}</td> <td>{row.prijs}</td> <td><button onClick={() => props.removeAlbum(index)}>Delete</button></td> </tr> ); }); return <tbody>{rows}</tbody>; }
Aan hetonClick
-event kennen we een anonieme functie toe, die de methoderemoveAlbum()
retourneert. Als we dat niet zouden doen dan zou deremoveAlbum()
functie bij het inladen van de HTML automatisch uitgevoerd worden. - Dit is het resultaat:
React Table Component With State
2020-04-14 12:21:23